package model

import (
	"fmt"
	"gitee.com/liumou_site/logger"
	"runtime"
	"sync"
	"sync/atomic"
	"time"
)

// MemoryMonitor 内存监控器
type MemoryMonitor struct {
	// 内存使用统计
	TotalAllocated int64 // 总分配内存（字节）
	TotalFreed     int64 // 总释放内存（字节）
	CurrentUsage   int64 // 当前使用内存（字节）
	PeakUsage      int64 // 峰值内存使用（字节）
	
	// 配置参数
	MaxMemory      int64   // 最大允许内存（字节）
	AlertThreshold float64 // 内存告警阈值（百分比）
	CheckInterval  time.Duration // 检查间隔
	
	// 控制字段
	isRunning      atomic.Bool
	stopChan       chan struct{}
	mu             sync.RWMutex
	
	// 缓冲区池
	bufferPool     *sync.Pool
	poolHits       int64
	poolMisses     int64
}

// NewMemoryMonitor 创建新的内存监控器
func NewMemoryMonitor(maxMemoryMB int64) *MemoryMonitor {
	mm := &MemoryMonitor{
		MaxMemory:      maxMemoryMB * 1024 * 1024, // 转换为字节
		AlertThreshold: 0.8, // 80% 告警阈值
		CheckInterval:  5 * time.Second,
		stopChan:       make(chan struct{}),
		bufferPool: &sync.Pool{
			New: func() interface{} {
				return make([]byte, 0, 1024*1024) // 1MB 缓冲区
			},
		},
	}
	
	// 初始化当前内存使用
	mm.updateMemoryStats()
	return mm
}

// Start 启动内存监控
func (mm *MemoryMonitor) Start() {
	if mm.isRunning.CompareAndSwap(false, true) {
		go mm.monitorLoop()
		logger.Info("内存监控已启动")
	}
}

// Stop 停止内存监控
func (mm *MemoryMonitor) Stop() {
	if mm.isRunning.CompareAndSwap(true, false) {
		select {
		case <-mm.stopChan:
			// 通道已关闭，跳过
		default:
			close(mm.stopChan)
		}
		logger.Info("内存监控已停止")
	}
}

// monitorLoop 监控循环
func (mm *MemoryMonitor) monitorLoop() {
	ticker := time.NewTicker(mm.CheckInterval)
	defer ticker.Stop()
	
	for {
		select {
		case <-ticker.C:
			mm.performMemoryCheck()
		case <-mm.stopChan:
			return
		}
	}
}

// performMemoryCheck 执行内存检查
func (mm *MemoryMonitor) performMemoryCheck() {
	mm.updateMemoryStats()
	
	currentUsage := atomic.LoadInt64(&mm.CurrentUsage)
	maxMemory := atomic.LoadInt64(&mm.MaxMemory)
	
	if maxMemory > 0 {
		usageRatio := float64(currentUsage) / float64(maxMemory)
		
		if usageRatio >= mm.AlertThreshold {
			logger.Warn(fmt.Sprintf("内存使用告警: %.2f%% (当前: %s, 限制: %s)", 
				usageRatio*100, 
				formatBytes(currentUsage), 
				formatBytes(maxMemory)))
		}
		
		if usageRatio >= 0.95 {
			logger.Error("内存使用超过95%，触发强制GC")
			mm.ForceGC()
		}
	}
	
	if mm.isMemoryLeakDetected() {
		logger.Warn("检测到可能的内存泄漏，建议检查代码")
		mm.ForceGC()
	}
}

// updateMemoryStats 更新内存统计
func (mm *MemoryMonitor) updateMemoryStats() {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	
	atomic.StoreInt64(&mm.CurrentUsage, int64(m.Alloc))
	
	mm.mu.Lock()
	if int64(m.Alloc) > mm.PeakUsage {
		mm.PeakUsage = int64(m.Alloc)
	}
	mm.mu.Unlock()
	
	atomic.StoreInt64(&mm.TotalAllocated, int64(m.TotalAlloc))
	atomic.StoreInt64(&mm.TotalFreed, int64(m.TotalAlloc-m.Alloc))
}

// isMemoryLeakDetected 检测内存泄漏
func (mm *MemoryMonitor) isMemoryLeakDetected() bool {
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	
	// 简单的内存泄漏检测逻辑
	// 如果内存使用持续增长且GC后下降不明显，可能存在泄漏
	staticLeak := m.HeapObjects > 100000 && m.HeapAlloc > uint64(mm.MaxMemory/2)
	growthLeak := m.Alloc > uint64(mm.MaxMemory*3/4) && m.NumGC < 10
	
	return staticLeak || growthLeak
}

// ForceGC 强制垃圾回收
func (mm *MemoryMonitor) ForceGC() {
	runtime.GC()
	runtime.Gosched()
	time.Sleep(100 * time.Millisecond)
	mm.updateMemoryStats()
	logger.Info("强制GC完成")
}

// GetBuffer 从缓冲区池获取缓冲区
func (mm *MemoryMonitor) GetBuffer(size int) []byte {
	if size <= 1024*1024 {
		buf := mm.bufferPool.Get().([]byte)
		atomic.AddInt64(&mm.poolHits, 1)
		return buf[:size]
	}
	
	atomic.AddInt64(&mm.poolMisses, 1)
	return make([]byte, size)
}

// PutBuffer 归还缓冲区到池
func (mm *MemoryMonitor) PutBuffer(buf []byte) {
	if cap(buf) == 1024*1024 {
		buf = buf[:0] // 重置长度
		mm.bufferPool.Put(buf)
	}
}

// GetMemoryStats 获取内存统计信息
func (mm *MemoryMonitor) GetMemoryStats() map[string]interface{} {
	mm.updateMemoryStats()
	
	var m runtime.MemStats
	runtime.ReadMemStats(&m)
	
	return map[string]interface{}{
		"current_usage":   atomic.LoadInt64(&mm.CurrentUsage),
		"peak_usage":      mm.getPeakUsage(),
		"total_allocated": atomic.LoadInt64(&mm.TotalAllocated),
		"total_freed":     atomic.LoadInt64(&mm.TotalFreed),
		"max_memory":      atomic.LoadInt64(&mm.MaxMemory),
		"usage_ratio":     float64(atomic.LoadInt64(&mm.CurrentUsage)) / float64(atomic.LoadInt64(&mm.MaxMemory)),
		"heap_objects":    int64(m.HeapObjects),
		"heap_alloc":      int64(m.HeapAlloc),
		"num_gc":          int64(m.NumGC),
		"gc_cpu_fraction": m.GCCPUFraction,
		"pool_hits":       atomic.LoadInt64(&mm.poolHits),
		"pool_misses":     atomic.LoadInt64(&mm.poolMisses),
	}
}

// getPeakUsage 获取峰值内存使用
func (mm *MemoryMonitor) getPeakUsage() int64 {
	mm.mu.RLock()
	defer mm.mu.RUnlock()
	return mm.PeakUsage
}

// SetMaxMemory 设置最大内存限制
func (mm *MemoryMonitor) SetMaxMemory(maxMemoryMB int64) {
	atomic.StoreInt64(&mm.MaxMemory, maxMemoryMB*1024*1024)
	logger.Info(fmt.Sprintf("最大内存限制设置为: %d MB", maxMemoryMB))
}

// formatBytes 格式化字节数
func formatBytes(bytes int64) string {
	const unit = 1024
	if bytes < unit {
		return fmt.Sprintf("%d B", bytes)
	}
	div, exp := int64(unit), 0
	for n := bytes / unit; n >= unit; n /= unit {
		div *= unit
		exp++
	}
	return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}